# -*- coding: utf-8 -*-

import htmlentitydefs
import json
import logging
import re
import sys
import urllib

languages = {
    'AFRIKAANS' : ('af', 'Afrikaans'),
    'ALBANIAN' : ('sq', 'Albanian'),
    'AMHARIC' : ('am', 'Amharic'),
    'ARABIC' : ('ar', 'Arabic'),
    'ARMENIAN' : ('hy', 'Armenian'),
    'AZERBAIJANI' : ('az', 'Azerbaijani'),
    'BASQUE' : ('eu', 'Basque'),
    'BELARUSIAN' : ('be', 'Belarusian'),
    'BENGALI' : ('bn', 'Bengali'),
    'BIHARI' : ('bh', 'Bihari'),
    'BULGARIAN' : ('bg', 'Bulgarian'),
    'BURMESE' : ('my', 'Burmese'),
    'CATALAN' : ('ca', 'Catalan'),
    'CHEROKEE' : ('chr', 'Cherokee'),
    'CHINESE' : ('zh', 'Chinese'),
    'CHINESE_SIMPLIFIED' : ('zh-CN', 'Chinese (simplified)'),
    'CHINESE_TRADITIONAL' : ('zh-TW', 'Chinese (traditional)'),
    'CROATIAN' : ('hr', 'Croatian'),
    'CZECH' : ('cs', 'Czech'),
    'DANISH' : ('da', 'Danish'),
    'DHIVEHI' : ('dv', 'Dhivehi'),
    'DUTCH' : ('nl',   'Dutch'),
    'ENGLISH' : ('en', 'English'),
    'ESPERANTO' : ('eo', 'Esperanto'),
    'ESTONIAN' : ('et', 'Estonian'),
    'FILIPINO' : ('tl', 'Filipino'),
    'FINNISH' : ('fi', 'Finnish'),
    'FRENCH' : ('fr', 'French'),
    'GALICIAN' : ('gl', 'Galician'),
    'GEORGIAN' : ('ka', 'Georgian'),
    'GERMAN' : ('de', 'German'),
    'GREEK' : ('el', 'Greek'),
    'GUARANI' : ('gn', 'Guarani'),
    'GUJARATI' : ('gu', 'Gujarati'),
    'HEBREW' : ('iw', 'Hebrew'),
    'HINDI' : ('hi', 'Hindi'),
    'HUNGARIAN' : ('hu', 'Hungarian'),
    'ICELANDIC' : ('is', 'Icelandic'),
    'INDONESIAN' : ('id', 'Indonesian'),
    'INUKTITUT' : ('iu', 'Inuktitut'),
    'IRISH' : ('ga', 'Irish'),
    'ITALIAN' : ('it', 'Italian'),
    'JAPANESE' : ('ja', 'Japanese'),
    'KANNADA' : ('kn', 'Kannada'),
    'KAZAKH' : ('kk', 'Kazakh'),
    'KHMER' : ('km', 'Khmer'),
    'KOREAN' : ('ko', 'Korean'),
    'KURDISH' : ('ku', 'Kurdish'),
    'KYRGYZ' : ('ky', 'Kyrgyz'),
    'LAOTHIAN' : ('lo', 'Loathian'),
    'LATVIAN' : ('lv', 'Latvian'),
    'LITHUANIAN' : ('lt', 'Lithuanian'),
    'MACEDONIAN' : ('mk', 'Macedonian'),
    'MALAY' : ('ms', 'Malay'),
    'MALAYALAM' : ('ml', 'Malayalam'),
    'MALTESE' : ('mt', 'Maltese'),
    'MARATHI' : ('mr', 'Marathi'),
    'MONGOLIAN' : ('mn', 'Mongolian'),
    'NEPALI' : ('ne', 'Nepali'),
    'NORWEGIAN' : ('no', 'Norwegian'),
    'ORIYA' : ('or', 'Oriya'),
    'PASHTO' : ('ps', 'Pashto'),
    'PERSIAN' : ('fa', 'Persian'),
    'POLISH' : ('pl', 'Polish'),
    'PORTUGUESE' : ('pt-PT', 'Portuguese'),
    'PUNJABI' : ('pa', 'Punjabi'),
    'ROMANIAN' : ('ro', 'Romanian'),
    'RUSSIAN' : ('ru', 'Russian'),
    'SANSKRIT' : ('sa', 'Sanskrit'),
    'SERBIAN' : ('sr', 'Serbian'),
    'SINDHI' : ('sd', 'Sindhi'),
    'SINHALESE' : ('si', 'Sinhalese'),
    'SLOVAK' : ('sk', 'Slovak'),
    'SLOVENIAN' : ('sl', 'Slovenian'),
    'SPANISH' : ('es', 'Spanish'),
    'SWAHILI' : ('sw', 'Swahili'),
    'SWEDISH' : ('sv', 'Swedish'),
    'TAJIK' : ('tg', 'Tajik'),
    'TAMIL' : ('ta', 'Tamil'),
    'TAGALOG' : ('tl', 'Tagalog'),
    'TELUGU' : ('te', 'Telugu'),
    'THAI' : ('th', 'Thai'),
    'TIBETAN' : ('bo', 'Tibetan'),
    'TURKISH' : ('tr', 'Turkish'),
    'UKRAINIAN' : ('uk', 'Ukrainian'),
    'URDU' : ('ur', 'Urdu'),
    'UZBEK' : ('uz', 'Uzbek'),
    'UIGHUR' : ('ug', 'Uighur'),
    'VIETNAMESE' : ('vi', 'Vietnamese'),
    'WELSH' : ('cy', 'Welsh'),
    'YIDDISH' : ('yi', 'Yiddish'),
    'UNKNOWN' : ('', 'Unknown'),
    }

translation_url = "http://ajax.googleapis.com/ajax/services/language/translate"
logger = logging.getLogger('translator')

def unescape(text):
    def fixup(m):
        text = m.group(0)
        if text[:2] == "&#":
            # character reference
            try:
                if text[:3] == "&#x":
                    return unichr(int(text[3:-1], 16))
                else:
                    return unichr(int(text[2:-1]))
            except ValueError:
                pass
        else:
            # named entity
            try:
                text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
            except KeyError:
                pass
        return text # leave as is
    return re.sub("&#?\w+;", fixup, text)

def split_text(text, max_length = 4500):
    '''Generate consecutive substrings of a maximum length.

    :param text: the text to split
    :param max_length: the maximum length of a substring
    :return: consecutive substrings
    '''

    for idx in xrange(0, len(text), max_length):
        yield text[idx:idx + max_length]

def translate(text, from_lang='UNKNOWN', to_lang='ENGLISH'):
    '''translate a piece of text using google

    :param text: the text to translate
    :param from_language: The language tuple to translate from. If
                          this is UNKNOWN, the source language will be
                          automatically determined.
    :param to_langauge: The language tuple to translate to.

    :except ValueError: If ``to_lanaguage`` is UNKNOWN
    :except ValueError: If either of the translation languages is not
                        supported
    '''

    from_code,from_hr = languages[from_lang]
    to_code,to_hr = languages[to_lang]

    logger.info('translating "%s" from %s to %s' % (text, from_hr, to_hr))

    params = {'langpair': '%s|%s' % (from_code, to_code),
              'v': '1.0'
              }

    rval = u''

    for text in split_text(text):
        params['q'] = text

        resp = urllib.urlopen('%s' % (translation_url),
                              data = urllib.urlencode(params)).read()
        resp = json.loads(resp)

        try:
            rval += resp['responseData']['translatedText']
        except (KeyError, TypeError):
            try:
                err_msg = resp['responseDetails']
            except KeyError:
                err_msg = 'Unexpected response data: %s' % resp
                
            logger.warning(err_msg)
            raise ValueError(err_msg)

    rval = unescape(rval)
    
    logger.info(u'translated to "{0}"'.format(rval))
        
    return rval

def test():
    print "What would you like to translate?"
    print "(Enter ctrl+c to exit)"
    while True:
        text = raw_input('#>  ')
        text = translate(text)
        print text

if __name__=='__main__':
    logging.basicConfig(level=logging.DEBUG)
    test()
